home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / etc / popen.c < prev    next >
C/C++ Source or Header  |  1991-05-29  |  2KB  |  109 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #if defined(LIBC_SCCS) && !defined(lint)
  8. static char sccsid[] = "@(#)popen.c    5.5 (Berkeley) 9/30/87";
  9. #endif LIBC_SCCS and not lint
  10.  
  11. #include <stdio.h>
  12. #include <signal.h>
  13. #include <sys/wait.h>
  14.  
  15. #define    tst(a,b)    (*mode == 'r'? (b) : (a))
  16. #define    RDR    0
  17. #define    WTR    1
  18.  
  19. extern    char *malloc();
  20.  
  21. static    int *popen_pid;
  22. static    int nfiles;
  23. static    int *child_status;
  24.  
  25.  
  26. FILE *
  27. popen(cmd,mode)
  28.     char *cmd;
  29.     char *mode;
  30. {
  31.     int p[2];
  32.     int myside, hisside, pid;
  33.  
  34.     if (nfiles <= 0)
  35.         nfiles = getdtablesize();
  36.     if (popen_pid == NULL) {
  37.         popen_pid = (int *)malloc((unsigned)
  38.             (nfiles * sizeof *popen_pid));
  39.         if (popen_pid == NULL)
  40.             return (NULL);
  41.         child_status = (int *)malloc((unsigned)
  42.             (nfiles * sizeof *child_status));
  43.         if (child_status == NULL)
  44.             return (NULL);
  45.         for (pid = 0; pid < nfiles; pid++) {
  46.             popen_pid[pid] = -1;
  47.             child_status[pid] = -1;
  48.         }
  49.     }
  50.     if (pipe(p) < 0)
  51.         return (NULL);
  52.     myside = tst(p[WTR], p[RDR]);
  53.     hisside = tst(p[RDR], p[WTR]);
  54.     if ((pid = vfork()) == 0) {
  55.         /* myside and hisside reverse roles in child */
  56.         close(myside);
  57.         if (hisside != tst(0, 1)) {
  58.             dup2(hisside, tst(0, 1));
  59.             close(hisside);
  60.         }
  61.         execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
  62.         _exit(127);
  63.     }
  64.     if (pid == -1) {
  65.         close(myside);
  66.         close(hisside);
  67.         return (NULL);
  68.     }
  69.     popen_pid[myside] = pid;
  70.     close(hisside);
  71.     return (fdopen(myside, mode));
  72. }
  73.  
  74. pclose(ptr)
  75.     FILE *ptr;
  76. {
  77.     int omask;
  78.     int child, pid, status;
  79.     int i;
  80.     int file;
  81.  
  82.     file = fileno(ptr);
  83.     if (popen_pid != NULL) {
  84.         child = popen_pid[file];
  85.         popen_pid[file] = -1;
  86.     } else {
  87.         child = -1;
  88.     }
  89.     fclose(ptr);
  90.     if (child == -1)
  91.         return (-1);
  92.     if (child_status[file] != -1) {
  93.         status = child_status[file];
  94.         child_status[file] = -1;
  95.         return (status);
  96.     }
  97.     omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
  98.     while ((pid = wait((union wait *) &status)) != child && pid != -1) {
  99.         for (i = 0; i < nfiles; i++) {
  100.         if (popen_pid[i] == pid) { 
  101.             child_status[i] = status;
  102.             break;
  103.         }
  104.         }
  105.     }
  106.     (void) sigsetmask(omask);
  107.     return (pid == -1 ? -1 : status);
  108. }
  109.